//
//  BaseMediaCaptureViewController.m
//  AnotherMediaTool
//
//  Created by fh on 2018/9/10.
//  Copyright © 2018年 fh. All rights reserved.
//

#import "GAKKIBaseMediaCaptureViewController.h"
#import <AssetsLibrary/AssetsLibrary.h>
#import <Photos/Photos.h>
#import "StudioRecordTool.h"
#import "StudioPreviewTool.h"
#import "StudioAuthorizationTool.h"
#import "PictureTakeView.h"
#import "VideoRecordView.h"
#import "AuthorizationView.h"
#import "FileManager.h"

@interface GAKKIBaseMediaCaptureViewController ()
/** 私有功能模式 */
@property (nonatomic, assign) MediaCaptureMode innerMediaCaptureMode;
/** 媒体采集工具 */
@property (nonatomic, strong) StudioRecordTool *recordTool;
/** 预览工具 */
@property (nonatomic, strong) StudioPreviewTool *previewTool;
/** 拍照UI视图 */
@property (nonatomic, strong) PictureTakeView *pictureTakeView;
/** 视频录制UI视图 */
@property (nonatomic, strong) VideoRecordView *videoRecordView;
/** 设备授权视图 */
@property (nonatomic, strong) AuthorizationView *authorizationView;
/** 是否应该隐藏电池栏 */
@property (nonatomic, assign) BOOL shouldHiddenStatusBar;
@end

@implementation GAKKIBaseMediaCaptureViewController

#pragma mark - Public
- (instancetype)initWithMode:(MediaCaptureMode)mediaCaptureMode {
    if (self = [super init]) {
        self.innerMediaCaptureMode = mediaCaptureMode;
        self.shouldRequestRemoteDataOnViewDidLoad = NO;
        self.shouldHiddenStatusBar = NO;
        self.isSavedPhotosAlbum = YES;
    }
    return self;
}

#pragma mark - Life cycle
- (void)viewDidLoad {
    [super viewDidLoad];
    [self configureMediaCaptureViewWithMode:self.innerMediaCaptureMode];
}
//- (void)viewWillAppear:(BOOL)animated {
//    [super viewWillAppear:animated];
//    [UIApplication sharedApplication].statusBarHidden = self.shouldHiddenStatusBar;
//}
- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];
    switch (self.innerMediaCaptureMode) {
        case MediaCaptureModeAudio: {
            // 录音暂时没有开发
            break;
        }
        case MediaCaptureModePhoto: {
            [self.recordTool configurePreviewWithView:self.pictureTakeView.preview frame:self.pictureTakeView.bounds];
            break;
        }
        case MediaCaptureModeVideo: {
            [self.recordTool configurePreviewWithView:self.videoRecordView.preview frame:self.videoRecordView.bounds];
            break;
        }
    }
}

#pragma mark - Over Write
//- (BOOL)prefersStatusBarHidden {
//    return self.shouldHiddenStatusBar;
//}
//- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation {
//    return UIStatusBarAnimationSlide;
//}

#pragma mark - Private

/**
 配置功能

 @param mode 功能模式
 */
- (void)configureMediaCaptureViewWithMode:(MediaCaptureMode)mode {
    switch (mode) {
        case MediaCaptureModeAudio: {
            break;
        }
        case MediaCaptureModePhoto: {
            self.view.backgroundColor = [UIColor whiteColor];
            WeakSelf;
            [StudioAuthorizationTool asyncJudgeAvailableWithCamera:^(BOOL cameraIsAvailable, BOOL cameraIsManual, NSString *cameraAvailableInfo) {
                if (cameraIsAvailable) {
                    weakSelf.shouldHiddenStatusBar = YES;
                    [weakSelf preparePictureTakeView];
                }else if (!cameraIsAvailable && cameraIsManual) {
                    weakSelf.shouldHiddenStatusBar = NO;
                    [weakSelf dismissViewControllerAnimated:YES completion:nil];
                }else if (!cameraIsAvailable && !cameraIsManual) {
                    if (kiOS8VerstionLater) {
                        weakSelf.shouldHiddenStatusBar = NO;
                        weakSelf.authorizationView.authorizationInfoLabel.text = @"温馨提示\n\n请在iPhone的\"设置-隐私\"选项中,允许访问您的摄像头";
                        [weakSelf.view addSubview:weakSelf.authorizationView];
                        [weakSelf.authorizationView mas_remakeConstraints:^(MASConstraintMaker *make) {
                            make.left.right.equalTo(@(0));
                            make.center.equalTo(weakSelf.view);
                        }];
                    } else {
                        weakSelf.shouldHiddenStatusBar = NO;
                        [weakSelf showLoadingWithRemindText:@"温馨提示\n授权失败,相机设备无法使用"];
                        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                            [weakSelf hiddenLoadingRemindText];
                            [weakSelf dismissViewControllerAnimated:YES completion:nil];
                        });
                    }
                }
            }];
            break;
        }
        case MediaCaptureModeVideo: {
            self.view.backgroundColor = [UIColor whiteColor];
            WeakSelf;
            [StudioAuthorizationTool asyncJudgeAvailableWithCamera:^(BOOL cameraIsAvailable, BOOL cameraIsManual, NSString *cameraAvailableInfo) {
                if (cameraIsAvailable) {
                
                    [StudioAuthorizationTool asyncJudgeAvailableWithMic:^(BOOL micIsAvailable, BOOL micIsManual, NSString *micAvailableInfo) {
                        if (micIsAvailable) {
                            weakSelf.shouldHiddenStatusBar = YES;
                            [weakSelf prepareVideoRecordView];
                        }else if (!micIsAvailable && micIsManual) {
                            weakSelf.shouldHiddenStatusBar = NO;
                            [weakSelf dismissViewControllerAnimated:YES completion:nil];
                        }else if (!micIsAvailable && !micIsManual) {
                            weakSelf.shouldHiddenStatusBar = NO;
                            weakSelf.authorizationView.authorizationInfoLabel.text = @"温馨提示\n\n请在iPhone的\"设置-隐私\"选项中,允许该应用程序访问您的麦克风";
                            [weakSelf.view addSubview:weakSelf.authorizationView];
                            [weakSelf.authorizationView mas_remakeConstraints:^(MASConstraintMaker *make) {
                                make.left.right.equalTo(@(0));
                                make.center.equalTo(weakSelf.view);
                            }];
                        }
                    }];
                    
                }else if (!cameraIsAvailable && cameraIsManual) {
                    weakSelf.shouldHiddenStatusBar = NO;
                    [weakSelf dismissViewControllerAnimated:YES completion:nil];
                }else if (!cameraIsAvailable && !cameraIsManual) {
                    if (kiOS8VerstionLater) {
                        weakSelf.shouldHiddenStatusBar = NO;
                        weakSelf.authorizationView.authorizationInfoLabel.text = @"温馨提示\n\n请在iPhone的\"设置-隐私\"选项中,允许该应用程序访问您的摄像头";
                        [weakSelf.view addSubview:weakSelf.authorizationView];
                        [weakSelf.authorizationView mas_remakeConstraints:^(MASConstraintMaker *make) {
                            make.left.right.equalTo(@(0));
                            make.center.equalTo(weakSelf.view);
                        }];
                    } else {
                        weakSelf.shouldHiddenStatusBar = NO;
                        [weakSelf showLoadingWithRemindText:@"温馨提示\n授权失败,相机设备无法使用"];
                        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                            [weakSelf hiddenLoadingRemindText];
                            [weakSelf dismissViewControllerAnimated:YES completion:nil];
                        });
                    }
                }
            }];
            break;
        }
    }
}

/**
 配置拍照界面和拍照功能
 */
- (void)preparePictureTakeView {
    WeakSelf;
    
    /**
     定义拍照返回事件回调

     @param button 拍照返回按钮
     @return void
     */
    self.pictureTakeView.backButtonClickedBlock = ^(UIButton *button) {
        [weakSelf.recordTool endCapture];
        [weakSelf dismissViewControllerAnimated:YES completion:nil];
    };
    
    /**
     定义拍照闪光灯事件回调

     @param button 拍照闪光灯按钮
     @param flashMode 闪光灯模式
     @return void
     */
    self.pictureTakeView.flashButtonClickedBlock = ^(UIButton *button, PictureTakeViewFlashMode flashMode) {
        switch (flashMode) {
            case PictureTakeViewFlashModeOff:
                [weakSelf.recordTool setFlashMode:FlashModeOff];
                break;
            case PictureTakeViewFlashModeAuto:
                [weakSelf.recordTool setFlashMode:FlashModeAuto];
                break;
            case PictureTakeViewFlashModeOn:
                [weakSelf.recordTool setFlashMode:FlashModeOn];
                break;
            default:
                break;
        }
    };
    
    /**
     定义拍照切换摄像头事件回调

     @param button 拍照摄像头切换按钮
     @return void
     */
    self.pictureTakeView.toggleButtonClickedBlock = ^(UIButton *button) {
        [weakSelf.recordTool toggleCamera];
    };
    
    /**
     定义拍照事件回调

     @param button 拍照按钮
     @return void
     */
    self.pictureTakeView.takePictureButtonClickedBlock = ^(UIButton *button) {
        button.enabled = NO;
        [weakSelf.recordTool takePictureWithCompletion:^(UIImage *photo, NSString *photoFilePath, NSError *photographError) {
            button.enabled = YES;
#ifdef DEBUG
            DBLog(@"%@ - %@ - %@",photo,photoFilePath,photographError);
#endif
            /// 需要添加照片预览功能
            [weakSelf.previewTool previewPhotoWithImage:photo previewSuperView:weakSelf.view previewSuperViewFrame:weakSelf.view.frame retakeClickBlock:^{
                
            } usePhotoClickBlock:^(UIImage *image) {
                if (weakSelf.isSavedPhotosAlbum) {
                    /// 保存照片到相册
                    UIImageWriteToSavedPhotosAlbum(image, weakSelf, @selector(image:didFinishSavingWithError:contextInfo:), nil);
                }
                [weakSelf dismissViewControllerAnimated:YES completion:nil];
                if (weakSelf.takePhotoResultBlock) {
                    weakSelf.takePhotoResultBlock(photo,photoFilePath);
                }
                FileModel *fileModel = [[FileModel alloc] init];
                fileModel.uniqueFileId = [[NSUUID UUID] UUIDString];
                fileModel.mimeType = [photoFilePath.lastPathComponent componentsSeparatedByString:@"."].lastObject;
                fileModel.originalFileName = [photoFilePath lastPathComponent];
                fileModel.fileName = [[FileManager sharedManager] createRandomNameWithMimeType:fileModel.mimeType];
                fileModel.URL = [NSURL fileURLWithPath:photoFilePath];
                fileModel.absoluteString = photoFilePath;
                fileModel.fileType = FileTypePhoto;
#ifdef DEBUG
                DBLog(@"生成的文件模型: %@",[fileModel yy_modelDescription]);
#endif
                if (weakSelf.resultBlock) {
                    weakSelf.resultBlock(fileModel);
                }
            }];
           
        }];
    };
    
    /**
     定义拍照聚焦事件回调

     @param tapGestureRecognizer 点击手势
     @param point 拍照聚焦的点
     @return void
     */
    self.pictureTakeView.focusPreviewClickedBlock = ^(UITapGestureRecognizer *tapGestureRecognizer, CGPoint point) {
        [weakSelf.recordTool focusAtPoint:point];
    };
  
    /**
     定义拍照AVCaptureDevice方式变焦回调

     @param percentScale 拍照变焦比例
     @return void
     */
    self.pictureTakeView.deviceZoomBlock = ^(CGFloat percentScale) {
        [weakSelf.recordTool setVideoZoomFactorWithPercent:percentScale];
    };
    
    [self.view addSubview:self.pictureTakeView];
    [self.pictureTakeView mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.top.left.right.equalTo(@(0));
        make.bottom.equalTo(@(0));
    }];
    /// 初始化拍照功能
    self.recordTool = [[StudioRecordTool alloc] initDefaultPhoto];
    /// 覆盖保存
    self.recordTool.coverStorePhoto = YES;
    /// 设置拍照模式最小变焦
    self.pictureTakeView.minScaleAndCropFactor = self.recordTool.photoMinScaleAndCropFactor;
    /// 设置拍照模式最大变焦
    self.pictureTakeView.maxScaleAndCropFactor = self.recordTool.photoMaxScaleAndCropFactor;
}

/**
 配置视频录制界面和视频录制功能
 */
- (void)prepareVideoRecordView {
    WeakSelf;
    
    /**
     定义视频返回事件回调

     @param button 返回按钮
     @return void
     */
    self.videoRecordView.backButtonClickedBlock = ^(UIButton *button) {
        [weakSelf.recordTool endCapture];
        [weakSelf dismissViewControllerAnimated:YES completion:nil];
    };
    
    /**
     定义视频闪光灯事件回调

     @param button 闪光灯按钮
     @param flashMode 闪光灯模式
     @return void
     */
    self.videoRecordView.flashButtonClickedBlock = ^(UIButton *button, VideoRecordViewFlashMode flashMode) {
        switch (flashMode) {
            case VideoRecordViewFlashModeOff:
                [weakSelf.recordTool setFlashMode:FlashModeOff];
                break;
            case VideoRecordViewFlashModeAuto:
                [weakSelf.recordTool setFlashMode:FlashModeAuto];
                break;
            case VideoRecordViewFlashModeOn:
                [weakSelf.recordTool setFlashMode:FlashModeOn];
                break;
        }
    };
    
    /**
     定义视频切换摄像头事件回调

     @param button 视频摄像头切换按钮
     @return void
     */
    self.videoRecordView.toggleButtonClickedBlock = ^(UIButton *button) {
        [weakSelf.recordTool toggleCamera];
    };
    
    /**
     定义视频录制事件回调

     @param recordingStatus 视频录制状态
     @param button 录制按钮
     @return void
     */
    self.videoRecordView.videoRecordButtonClickedBlock = ^(BOOL recordingStatus, CaptureButton *button) {
        if (recordingStatus) {
            [weakSelf.recordTool beginCapture];
            [weakSelf.recordTool startVideoRecord];
            [weakSelf.recordTool watchVideoRecordProcessWithBlock:^(CGFloat processTime) {
                [weakSelf updateVideoRecordTimeStrWithVideoProcessTime:processTime];
            }];
        }else {
            [weakSelf showLoadingWithRemindText:@"正在处理..."];
            [weakSelf.recordTool stopVideoRecordWithAllDetailCompletion:^(NSURL *outputFileURL, UIImage *videoImage, NSError *videoRecordError, int videoDuration, float videoSize) {
                [weakSelf hiddenLoadingRemindText];
#ifdef DEBUG
                DBLog(@"录制结果: %@ --- 视频截图: %@ --- 录制错误信息: %@ --- 视频时长: %d --- 视频大小: %f",outputFileURL,videoImage,videoRecordError,videoDuration,videoSize);
#endif
                if (weakSelf.isSavedPhotosAlbum) {
                    if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(outputFileURL.path)) {
                        //保存视频到相册
                        UISaveVideoAtPathToSavedPhotosAlbum(outputFileURL.path, weakSelf, @selector(video:didFinishSavingWithError:contextInfo:), nil);
                    }
                }
                if (videoDuration > 0) {
                    [weakSelf.videoRecordView previewVideoWithVideoURL:outputFileURL videoImage:videoImage videoDuration:videoDuration videoSize:videoSize];
                }
            }];
        }
    };
    
    /**
     定义视频聚焦事件回调

     @param tapGestureRecognizer 点击手势
     @param point 视频聚焦的点
     @return void
     */
    self.videoRecordView.focusPreviewClickedBlock = ^(UITapGestureRecognizer *tapGestureRecognizer, CGPoint point) {
        [weakSelf.recordTool focusAtPoint:point];
    };
    
    /**
     定义视频AVCaptureDevice方式变焦回调

     @param percentScale 视频变焦比例
     @return void
     */
    self.videoRecordView.deviceZoomBlock = ^(CGFloat percentScale) {
        [weakSelf.recordTool setVideoZoomFactorWithPercent:percentScale];
    };
    
    [self.view addSubview:self.videoRecordView];
    [self.videoRecordView mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.top.bottom.left.right.equalTo(@(0));
    }];
    /// 初始化视频录制功能
    self.recordTool = [[StudioRecordTool alloc] initDefaultVideo];
    // 使用系统方式设置视频输出压缩质量
//    self.recordTool.configuration.videoConfigurationMode = SCVideoConfigurationModeOutputSettingsAssistant;
//    self.recordTool.configuration.videoOutputSettingsPreset = SCOutputSettingsPreset1920x1080;
    self.recordTool.configuration.videoAverageBitRate = 12000000;
    /// 覆盖保存
    self.recordTool.coverStoreVideo = YES;
    /// 视频录制模式最大变焦
    self.videoRecordView.minScaleAndCropFactor = self.recordTool.photoMinScaleAndCropFactor;
    /// 视频录制模式最大变焦
    self.videoRecordView.maxScaleAndCropFactor = self.recordTool.photoMaxScaleAndCropFactor;
    
    // 视频被打断事件回调(除了切到后台的事件,app切换到后台的事件单独处理)
    self.recordTool.videoRecordWasInterruptedBlock = ^(NSInteger interruptedReason) {
        [weakSelf dismissViewControllerAnimated:YES completion:nil];
    };
    // app切换到后台自动结束录制视频
    self.recordTool.videoRecordDidEnterBackgroundWasInterruptedBlock = ^(NSURL *outputFileURL, NSError *videoRecordError, int videoDuration, float videoSize) {
        [weakSelf.previewTool previewVideoWithoutRelevantInfoWithVideoURL:outputFileURL preview:weakSelf.view previewFrame:weakSelf.view.frame];
    };
}

/**
 更新录制时间

 @param processTime 录制时间
 */
- (void)updateVideoRecordTimeStrWithVideoProcessTime:(CGFloat)processTime {
    NSInteger houri = (NSInteger)processTime / 60 / 60;
    NSInteger mini = (NSInteger)processTime / 60;
    NSInteger seci = (NSInteger)processTime % 60;
    self.videoRecordView.recordTimeLabel.text = [NSString stringWithFormat:@"%.2ld:%.2ld:%.2ld",houri, mini,seci];
}

#pragma mark - Event

/**
 取消设备授权处理方法

 @param button 取消授权按钮
 */
- (void)authorizationViewCancleButtonAction:(UIButton *)button {
    [self dismissViewControllerAnimated:YES completion:nil];
}

/**
 保存照片完成之后的回调

 @param image 要保存的照片
 @param error 错误信息
 @param contextInfo 上下文信息
 */
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
#ifdef DEBUG
    NSLog(@"保存照片完成之后的线程%@",[NSThread currentThread]);
    if (!error) {
        NSLog(@"照片保存到相册成功");
    }
    NSLog(@"image = %@, error = %@, contextInfo = %@", image, error, contextInfo);
#endif
    if (error) {
        PHAuthorizationStatus authStatus = [PHPhotoLibrary authorizationStatus];
        if (authStatus == PHAuthorizationStatusRestricted|| authStatus == PHAuthorizationStatusDenied) {
            [self showTipViewWithInfo:@"保存照片到相册失败，请检查相册的访问权限"];
        }else {
            [self showTipViewWithInfo:error.localizedDescription];
        }
    }
}

/**
 保存视频完成之后的回调

 @param videoPath 要保存的视频路径
 @param error 错误信息
 @param contextInfo 上下文信息
 */
- (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
#ifdef DEBUG
    NSLog(@"保存视频完成之后的线程%@",[NSThread currentThread]);
    if (!error) {
        NSLog(@"视频保存到相册成功");
    }
    NSLog(@"videoPath = %@, error = %@-%@, contextInfo = %@", videoPath, error, error.localizedDescription, contextInfo);
#endif
    if (error) {
        PHAuthorizationStatus authStatus = [PHPhotoLibrary authorizationStatus];
        if (authStatus == PHAuthorizationStatusRestricted|| authStatus == PHAuthorizationStatusDenied) {
            [self showTipViewWithInfo:@"保存视频到相册失败，请检查相册的访问权限"];
        }else {
            [self showTipViewWithInfo:error.localizedDescription];
        }
    }
}

#pragma mark - Setter and getter
- (StudioPreviewTool *)previewTool {
    if (!_previewTool) {
        _previewTool = [[StudioPreviewTool alloc] init];
        _previewTool.repeatPreviewVideo = YES;
    }
    return _previewTool;
}
- (PictureTakeView *)pictureTakeView {
    if (!_pictureTakeView) {
        _pictureTakeView = [[PictureTakeView alloc] init];
    }
    return _pictureTakeView;
}
- (VideoRecordView *)videoRecordView {
    if (!_videoRecordView) {
        _videoRecordView = [[VideoRecordView alloc] init];
        WeakSelf;
        _videoRecordView.sureButtonClickedBlock = ^(UIButton *button, NSURL *videoURL, UIImage *videoImage) {
            [weakSelf dismissViewControllerAnimated:YES completion:nil];
            if (weakSelf.recordVideoResultBlock) {
                weakSelf.recordVideoResultBlock(videoURL);
            }
            FileModel *fileModel = [[FileModel alloc] init];
            fileModel.uniqueFileId = [[NSUUID UUID] UUIDString];
            fileModel.mimeType = [videoURL.lastPathComponent componentsSeparatedByString:@"."].lastObject;
            fileModel.originalFileName = [videoURL.absoluteString lastPathComponent];
            fileModel.fileName = [[FileManager sharedManager] createRandomNameWithMimeType:fileModel.mimeType];
            fileModel.URL = videoURL;
            fileModel.absoluteString = videoURL.absoluteString;
            fileModel.fileType = FileTypeVideo;
            fileModel.thumbnail = videoImage;
#ifdef DEBUG
            DBLog(@"生成的文件模型: %@",[fileModel yy_modelDescription]);
#endif
            if (weakSelf.resultBlock) {
                weakSelf.resultBlock(fileModel);
            }
        };
        _videoRecordView.cancleButtonClickedBlock = ^(UIButton *button) {
#ifdef DEBUG
            DBLog(@"重拍视频");
#endif
        };
    }
    return _videoRecordView;
}
- (AuthorizationView *)authorizationView {
    if (!_authorizationView) {
        _authorizationView = [[AuthorizationView alloc] init];
        [_authorizationView.cancleButton addTarget:self action:@selector(authorizationViewCancleButtonAction:) forControlEvents:UIControlEventTouchUpInside];
    }
    return _authorizationView;
}

@end

